﻿using System;
using UnityEngine;

namespace Assets.Scripts.Map
{

    [CreateAssetMenu(fileName = "NewMapData", menuName = "MapData")]
    public class MapData : ScriptableObject
    {
        [SerializeField]
        bool[] storage;
        [SerializeField]
        int storage_width;

        bool[,] data;
        public int Width
        {
            get
            {
                if (data == null)
                {
                    return 0;
                }
                return data.GetLength(0);
            }
        }

        public int Height
        {
            get
            {
                if (data == null)
                {
                    return 0;
                }
                return data.GetLength(1);
            }
        }

        public bool Inited
        {
            get
            {
                if (data == null)
                    return false;
                return Width == storage_width;
            }
        }


        public void Init()
        {
            if (storage.Length > 0 && storage_width > 0)
            {
                int height = storage.Length / storage_width;
                data = new bool[storage_width, height];
                for (int x = 0; x < storage_width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        data[x, y] = storage[y * storage_width + x];
                    }
                }
            }
        }

        /// <summary>
        /// 是否可通过
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool Get(int x, int y)
        {
            if (x < 0 || x >= Width)
            {
                //Debug.LogError(string.Format("Error : x->{0} width->{1}", x, width));
                return false;
            }

            if (y < 0 || y >= Height)
            {
                //Debug.LogError(string.Format("Error: y->{0} height->{1}", y, height));
                return false;
            }
            return data[x, y];
        }

        public bool this[int x, int y]
        {
            get
            {
                return Get(x, y);
            }
        }

        public bool this[V2 v]
        {
            get
            {
                return Get(v.X, v.Y);
            }
        }

        public void Regenerate(int h, int w, float blockRate)
        {
            data = MapDataGenerator.Generate_1(h, w, blockRate);
            storage = new bool[h * w];
            storage_width = w;
            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    storage[j * w + i] = data[i, j];
                }
            }
        }
    }

    public struct V2 : IEquatable<V2>
    {
        public int X;
        public int Y;

        public static int GetG(V2 n, V2 m)
        {
            if (n.X == m.X && n.Y == m.Y)
                return 0;

            if (n.X != m.X && n.Y != m.Y)
            {
                return 14;
            }

            return 10;
        }

        public static int GetH(V2 n, V2 m)
        {
            return (Mathf.Abs(n.X - m.X) + Mathf.Abs(n.Y - m.Y)) * 10;
        }

        public override bool Equals(object obj)
        {
            return obj is V2 v && Equals(v);
        }

        public bool Equals(V2 other)
        {
            return X == other.X && Y == other.Y;
        }

        public override int GetHashCode()
        {
            return HashCode.Combine(X, Y);
        }

        public static V2 operator +(V2 a, V2 b) => new() { X = a.X + b.X, Y = a.Y + b.Y };
        public static V2 operator -(V2 a, V2 b) => new() { X = a.X - b.X, Y = a.Y - b.Y };


        public static bool operator ==(V2 a, V2 b) => a.X == b.X && a.Y == b.Y;
        public static bool operator !=(V2 a, V2 b) => a.X != b.X || a.Y != b.Y;

    }
}